using B.S.XZYData.Api.Wrter.Application.Command.Plan;
using B.S.XZYData.Domain.LJC;
using B.S.XZYData.ErrorCode;
using B.S.XZYData.Infrastructure.Interface;
using MediatR;
using System.Transactions;
using Yitter.IdGenerator;
using System.Collections.Generic;

namespace B.S.XZYData.Api.Wrter.Application.Handler.Plan
{
	/// <summary>
	/// 保存生产计划处理器（主表+子表一起保存）
	/// </summary>
	public class SavePlanHandler : IRequestHandler<SavePlanCommand, ApiResult<int>>
	{
		private readonly IBaseRepository<PlanModel> _planRepo;
		private readonly IBaseRepository<ProductModel> _productRepo;
		private readonly ILogger<SavePlanHandler> _logger;

		/// <summary>
		/// 构造函数
		/// </summary>
		public SavePlanHandler(
			IBaseRepository<PlanModel> planRepo,
			IBaseRepository<ProductModel> productRepo,
			ILogger<SavePlanHandler> logger)
		{
			_planRepo = planRepo;
			_productRepo = productRepo;
			_logger = logger;
		}

		/// <summary>
		/// 保存生产计划
		/// </summary>
		/// <param name="request">命令</param>
		/// <param name="cancellationToken">取消令牌</param>
		/// <returns>返回统一包装类</returns>
		public async Task<ApiResult<int>> Handle(SavePlanCommand request, CancellationToken cancellationToken)
		{
			var res = new ApiResult<int>();

					try
		{
			// 设置默认操作人，避免空值问题
			if (string.IsNullOrWhiteSpace(request.OperateBy))
			{
				request.OperateBy = "System";
			}

			_logger.LogInformation($"开始保存生产计划，单号: {request.Code}，操作人: {request.OperateBy}，产品数量: {request.Products?.Count ?? 0}");

			// 基础验证
			var validationResult = await ValidateRequest(request);
			if (validationResult != null)
			{
				_logger.LogWarning($"生产计划验证失败，单号: {request.Code}，错误: {validationResult.Msg}");
				return validationResult;
			}

			_logger.LogInformation($"生产计划验证通过，单号: {request.Code}");

			// 获取需要处理的产品（未标记移除的产品）
			var productsToProcess = request.Products?.Where(x => !x.IsRemoved).ToList() ?? new List<SavePlanProductCommand>();
			var productCodes = productsToProcess.Select(x => x.ProductCode).Distinct().ToList();
			var existingProducts = _productRepo.GetAll().Where(x => productCodes.Contains(x.Code)).ToList();

			_logger.LogInformation($"产品验证结果，单号: {request.Code}，待处理产品数量: {productsToProcess.Count}，现有产品数量: {existingProducts.Count}");

			// 使用事务确保数据一致性
			using var scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled);

			_logger.LogInformation($"开始事务处理，单号: {request.Code}");

			int planId = request.Id;
			PlanModel planModel;

			if (planId == 0)
			{
				// 新增计划
				_logger.LogInformation($"创建新计划，单号: {request.Code}");
				planModel = await CreateNewPlan(request);
				planId = planModel.Id;
				_logger.LogInformation($"新计划创建成功，单号: {request.Code}，ID: {planId}");
			}
			else
			{
				// 编辑计划
				_logger.LogInformation($"更新现有计划，单号: {request.Code}，ID: {planId}");
				var updateResult = await UpdateExistingPlan(request, planId);
				if (updateResult != null)
				{
					_logger.LogWarning($"计划更新失败，单号: {request.Code}，错误: {updateResult.Msg}");
					return updateResult;
				}
				_logger.LogInformation($"计划更新成功，单号: {request.Code}，ID: {planId}");
			}

			// 处理产品数据 - 关键：设置产品的PlanId字段建立关联
			_logger.LogInformation($"开始处理计划产品，单号: {request.Code}，计划ID: {planId}");
			await ProcessPlanProducts(request.Products ?? new List<SavePlanProductCommand>(), planId, request.OperateBy);
			_logger.LogInformation($"计划产品处理完成，单号: {request.Code}，计划ID: {planId}");

			scope.Complete();
			_logger.LogInformation($"事务提交成功，单号: {request.Code}，计划ID: {planId}");

			res.Data = planId;
			res.Code = ApiEnum.Success;
			res.Msg = "保存成功";

			_logger.LogInformation($"用户 {request.OperateBy} 成功保存生产计划，ID: {planId}，单号: {request.Code}，产品数量: {request.Products?.Count ?? 0}");
		}
			catch (Exception ex)
			{
				res.Code = ApiEnum.Fail;
				res.Msg = $"保存失败: {ex.Message}";
				_logger.LogError(ex, $"保存生产计划失败，单号: {request.Code}，操作人: {request.OperateBy}，详细错误: {ex}");
			}

			return res;
		}

		/// <summary>
		/// 验证请求数据
		/// </summary>
		private Task<ApiResult<int>?> ValidateRequest(SavePlanCommand request)
		{
			// 验证产品数量
			if (request.Products == null || !request.Products.Any())
			{
				return Task.FromResult<ApiResult<int>?>(new ApiResult<int>
				{
					Code = ApiEnum.Fail,
					Msg = "请至少添加一个产品"
				});
			}

			// 获取需要处理的产品（未标记移除的）
			var productsToValidate = request.Products.Where(x => !x.IsRemoved).ToList();
			
			// 预加载存在的产品用于验证
			var productCodes = productsToValidate.Select(x => x.ProductCode).Distinct().ToList();
			var existingProducts = _productRepo.GetAll()
				.Where(x => productCodes.Contains(x.Code))
				.ToList();

			foreach (var product in productsToValidate)
			{
				// 验证必填字段
				if (string.IsNullOrWhiteSpace(product.ProductCode))
				{
					return Task.FromResult<ApiResult<int>?>(new ApiResult<int>
					{
						Code = ApiEnum.Fail,
						Msg = "产品编号不能为空"
					});
				}

				if (string.IsNullOrWhiteSpace(product.ProductName))
				{
					return Task.FromResult<ApiResult<int>?>(new ApiResult<int>
					{
						Code = ApiEnum.Fail,
						Msg = $"产品 {product.ProductCode} 的产品名称不能为空"
					});
				}

				// 如果是更新现有产品，验证产品是否存在
				if (product.Id > 0)
				{
					var existingProduct = existingProducts.FirstOrDefault(x => x.Code == product.ProductCode);
					if (existingProduct == null || existingProduct.Id != product.Id)
					{
						return Task.FromResult<ApiResult<int>?>(new ApiResult<int>
						{
							Code = ApiEnum.Fail,
							Msg = $"要更新的产品 {product.ProductCode} 不存在或ID不匹配"
						});
					}
				}
			}

			return Task.FromResult<ApiResult<int>?>(null);
		}

		/// <summary>
		/// 创建新计划
		/// </summary>
		private async Task<PlanModel> CreateNewPlan(SavePlanCommand request)
		{
			// 验证计划单号唯一性
			var existingPlan = _planRepo.GetAll()
				.Where(x => x.Code == request.Code)
				.ToList()
				.FirstOrDefault();

			if (existingPlan != null)
			{
				throw new InvalidOperationException($"计划单号 {request.Code} 已存在");
			}

			var planModel = new PlanModel
			{
				Code = request.Code,
				Remark = request.Remark,
				CreateTime = DateTime.Now,
				CreateBy = request.OperateBy,
				UpdateTime = DateTime.Now,
				UpdateBy = request.OperateBy
			};

					var newId = await _planRepo.CreateAsync(planModel);
		planModel.Id = newId;
		
		_logger.LogInformation($"新计划创建成功，获得ID: {newId}");
		return planModel;
		}

		/// <summary>
		/// 更新现有计划
		/// </summary>
		private async Task<ApiResult<int>?> UpdateExistingPlan(SavePlanCommand request, int planId)
		{
			var planModel = _planRepo.GetAll()
				.Where(x => x.Id == planId)
				.ToList()
				.FirstOrDefault();

			if (planModel == null)
			{
				return new ApiResult<int>
				{
					Code = ApiEnum.Fail,
					Msg = "计划不存在"
				};
			}

			// 检查计划单号唯一性（排除自己）
			var existingPlan = _planRepo.GetAll()
				.Where(x => x.Code == request.Code && x.Id != planId)
				.ToList()
				.FirstOrDefault();

			if (existingPlan != null)
			{
				return new ApiResult<int>
				{
					Code = ApiEnum.Fail,
					Msg = $"计划单号 {request.Code} 已存在"
				};
			}

			// 更新主表
			planModel.Code = request.Code;
			planModel.Remark = request.Remark;
			planModel.UpdateTime = DateTime.Now;
			planModel.UpdateBy = request.OperateBy;

			await _planRepo.UpdateAsync(planModel);
			return null;
		}

		/// <summary>
		/// 处理计划产品数据 - 核心：设置产品的PlanId字段建立关联
		/// </summary>
		private async Task ProcessPlanProducts(List<SavePlanProductCommand> products, int planId, string operateBy)
		{
			// 获取需要移除关联的产品
			var productsToRemove = products.Where(x => x.IsRemoved && x.Id > 0).ToList();
			foreach (var removeProduct in productsToRemove)
			{
				var existingProduct = _productRepo.GetAll()
					.Where(x => x.Id == removeProduct.Id)
					.ToList()
					.FirstOrDefault();

				if (existingProduct != null)
				{
					// 解除计划关联
					existingProduct.PlanId = null;
					existingProduct.UpdateTime = DateTime.Now;
					await _productRepo.UpdateAsync(existingProduct);
					_logger.LogInformation($"解除产品计划关联，产品ID: {removeProduct.Id}，产品名称: {removeProduct.ProductName}");
				}
			}

			// 处理需要关联到计划的产品
			var productsToProcess = products.Where(x => !x.IsRemoved).ToList();
			foreach (var product in productsToProcess)
			{
				if (product.Id == 0)
				{
					// 新增产品并关联到计划
					var newProduct = new ProductModel
					{
						Code = product.ProductCode,
						Name = product.ProductName,
						Spec = product.Spec,
						Unit = product.Unit,
						Producer = product.Producer,
						ProductionStartTime = product.ProductionStartTime,
						ProductionEndTime = product.ProductionEndTime,
						PlanId = planId,
						CreateTime = DateTime.Now,
						UpdateTime = DateTime.Now
					};

					var newProductId = await _productRepo.CreateAsync(newProduct);
					newProduct.Id = newProductId;
					_logger.LogInformation($"新增产品并关联计划成功，产品ID: {newProductId}，产品名称: {product.ProductName}，计划ID: {planId}");
				}
				else
				{
					// 更新现有产品并关联到计划
					var existingProduct = _productRepo.GetAll()
						.Where(x => x.Id == product.Id)
						.ToList()
						.FirstOrDefault();

					if (existingProduct != null)
					{
						existingProduct.Code = product.ProductCode;
						existingProduct.Name = product.ProductName;
						existingProduct.Spec = product.Spec;
						existingProduct.Unit = product.Unit;
						existingProduct.Producer = product.Producer;
						existingProduct.ProductionStartTime = product.ProductionStartTime;
						existingProduct.ProductionEndTime = product.ProductionEndTime;
						existingProduct.PlanId = planId;
						existingProduct.UpdateTime = DateTime.Now;

						await _productRepo.UpdateAsync(existingProduct);
						_logger.LogInformation($"更新产品并关联计划，产品ID: {existingProduct.Id}，产品名称: {product.ProductName}，计划ID: {planId}");
					}
				}
			}

			_logger.LogInformation($"计划产品处理完成，计划ID: {planId}，处理产品数量: {productsToProcess.Count}");
		}
	}
} 